package com.yonyou.pmclouds.project.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.entity.PageObject;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.basecom.util.ChineseStringUtils;
import com.yonyou.pmclouds.basecom.util.CommonProgramConsts;
import com.yonyou.pmclouds.offline.aspect.Offline;
import com.yonyou.pmclouds.offline.entity.OffLineDataKeyConst;
import com.yonyou.pmclouds.offline.entity.OffLineInvocationContext;
import com.yonyou.pmclouds.outter.enterprise.EnterpriseInfoQuery;
import com.yonyou.pmclouds.outter.user.UserInfoQuery;
import com.yonyou.pmclouds.outter.user.UserOperator;
import com.yonyou.pmclouds.project.entity.ProjectRefVO;
import com.yonyou.pmclouds.project.entity.ProjectSearchConditionVO;
import com.yonyou.pmclouds.project.entity.ProjectVO;
import com.yonyou.pmclouds.project.entity.ProjectWithProblemVO;
import com.yonyou.pmclouds.team.entity.TeamEnterpriseRefVO;
import com.yonyou.pmclouds.team.entity.TeamEnterpriseVO;
import com.yonyou.pmclouds.team.entity.TeamMemberVO;
import com.yonyou.pmclouds.team.rmiitf.ProjectRefWithTeamQuery;
import lombok.Data;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.io.Serializable;
import java.util.*;

import static com.yonyou.pmclouds.basecom.PMControllerConst.DEFAULT_PAGE_PAGE_START;

@RestController
@RequestMapping(value = {"/mobile/projectInTeam", "/projectInTeam"})
@Offline(dataFrom = OffLineDataKeyConst.DATA_FROM_PROJECT)
public class ProjectCommonRefController {

    private static final String[] USER_ID_FIELDS = {ProjectVO.MANAGER, ProjectVO.CREATOR};
    private static final String[] USER_NAME_FIELDS = {ProjectVO.MANAGER_NAME, ProjectVO.CREATOR_NAME};
    /**
     * 项目位置匹配的范围，5公里
     */
    private static final Double PROJECT_ADDRESS_RANGE = 5000d;

    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private ProjectRefWithTeamQuery query;
    @Autowired
    private UserInfoQuery userInfoQuery;
    @Autowired
    private UserOperator userOperator;
    @Autowired
    private EnterpriseInfoQuery enterpriseInfoQuery;

    @GetMapping(value = "/list")
    public PageObject<?> list(@RequestParam(name = "pkTenant", required = false) String pkTenant,
                              @RequestParam(name = "isMakeBill", required = false, defaultValue = "false") Boolean isMakeBill,
                              @RequestParam(name = "projectState", required = false) Byte[] projectState,
                              @RequestParam(name = "pageStart", required = false, defaultValue = DEFAULT_PAGE_PAGE_START) String pageStart,
                              @RequestParam(name = "pageSize", required = false, defaultValue = "1000") String pageSize,
                              @RequestParam(name = "longitude", defaultValue = "-1") double longitude,
                              @RequestParam(name = "latitude", defaultValue = "-1") double latitude) throws BusinessException, IOException {
        //判断租户是否为空，因为是要查询在这个租户下的项目
        if (StringUtils.isEmpty(pkTenant)) {
            if (StringUtils.isEmpty(RuntimeEnvironment.getTenantId())) {
                throw new IllegalArgumentException("pkTenant is null ");
            }
            pkTenant = RuntimeEnvironment.getTenantId();
        }

        List<String> pkRoles = getRolesByUser(RuntimeEnvironment.getLoginUserId(), pkTenant);

        PageObject<ProjectRefVO> projectPage = null;
        if (isMakeBill != null && isMakeBill) {
            projectPage = query.queryProjectWithDistanceOfUser(RuntimeEnvironment.getLoginUserId(), pkTenant, projectState,
                    Integer.valueOf(pageStart), Integer.valueOf(pageSize), null, longitude, latitude);
        } else {
            //根据租户下的用户所属的每个角色身份查询其所应的所属组织下的所有项目以及用户所属团队下的所有项目。
            projectPage = query.queryProjectWithDistanceOfUser(RuntimeEnvironment.getLoginUserId(), pkTenant, projectState,
                    Integer.valueOf(pageStart), Integer.valueOf(pageSize), pkRoles.toArray(new String[0]), longitude, latitude);
        }

        // todo 只是为整理资料做的翻译 以后整理资料就别调这个了
        userInfoQuery.tranUserInfoField(projectPage.getObjects(), new String[]{ProjectVO.MANAGER}, new String[]{ProjectVO.MANAGER_NAME});

        return projectPage;
    }

    public List<String> getRolesByUser(String userId, String tenantId) throws IOException {
        Map map = userOperator.queryRoleByUserId(tenantId, userId);
        List<String> pkRoles = new ArrayList<>();
        if (map != null && map.get("data") != null) {
            pkRoles = (ArrayList) map.get("data");
        }
        return pkRoles;
    }

    @Offline(operate = "before")
    public Object offlineBefore(Object object) throws IOException {
        if (!(object instanceof OffLineInvocationContext)) {
            return object;
        }

        OffLineInvocationContext invocationContext = (OffLineInvocationContext) object;
        String userId = invocationContext.getUserId();
        String tenantId = invocationContext.getTenantId();

        return getRolesByUser(userId, tenantId);
    }

    @Offline
    public Object offlineAfter(Object object) {

        PageObject<Object> pageObject = (PageObject<Object>) object;
        Object[] projectRefVOS = pageObject.getObjects();

        for (Object projectRef : projectRefVOS) {
            //设置施工单位企业信息
            ProjectRefVO projectRefVO = (ProjectRefVO) projectRef;
            List<TeamEnterpriseRefVO> constructionUnit = projectRefVO.getConstructionUnit();
            if (constructionUnit != null) {
                TeamEnterpriseRefVO[] teamEnterpriseRefVOS = constructionUnit.toArray(new TeamEnterpriseRefVO[]{});
                enterpriseInfoQuery.tranEntInfoField(teamEnterpriseRefVOS, new String[]{TeamEnterpriseVO.PK_ENTERPRISE}, new String[]{TeamEnterpriseVO.ENTERPRISE_NAME});
            }

            //设置监理单位企业信息
            List<TeamEnterpriseRefVO> supervisionUnit = projectRefVO.getSupervisionUnit();
            if (supervisionUnit != null) {
                TeamEnterpriseRefVO[] teamEnterpriseRefVOS1 = supervisionUnit.toArray(new TeamEnterpriseRefVO[]{});
                enterpriseInfoQuery.tranEntInfoField(teamEnterpriseRefVOS1, new String[]{TeamEnterpriseVO.PK_ENTERPRISE}, new String[]{TeamEnterpriseVO.ENTERPRISE_NAME});
            }

            //设置人员用户信息及对人员排序
            List<TeamMemberVO> teamMemberVOS = projectRefVO.getTeamMemberVOS();
            if (teamMemberVOS != null) {
                TeamMemberVO[] teamMembers = teamMemberVOS.toArray(new TeamMemberVO[]{});
                userInfoQuery.tranUserInfoField(teamMembers, new String[]{TeamMemberVO.PK_USER}, new String[]{TeamMemberVO.USER_NAME});
                if (!ArrayUtils.isEmpty(teamMembers)) {
                    Arrays.sort(teamMembers, new Comparator<TeamMemberVO>() {
                        @Override
                        public int compare(TeamMemberVO o1, TeamMemberVO o2) {
                            if (o1 == o2) {
                                return 0;
                            }
                            if (o1 == null) {
                                return 1;
                            }
                            if (o2 == null) {
                                return -1;
                            }
                            return ChineseStringUtils.compareInDict(o1.getUserName(), o2.getUserName());
                        }
                    });
                }
            }
        }

        return object;
    }


    @RequestMapping(value = "/listWithProblem")
    public PageObject<?> listWithProblem(@RequestBody ListWithProblemParam param) throws BusinessException, IOException {
        if (param == null || param.getPkTenant() == null) return null;
        Byte state = param.getProjectState() == null ? null : Byte.parseByte(param.getProjectState());
        Map map = userOperator.queryRoleByUserId(param.getPkTenant(), RuntimeEnvironment.getLoginUserId());
        List<String> pkRoles = new ArrayList<>();
        if (map != null && map.get("data") != null) pkRoles = (ArrayList) map.get("data");
        PageObject<?> result = query.queryOfUserProblem(RuntimeEnvironment.getLoginUserId(), param.getPkTenant(), state,
                Integer.valueOf(param.getPageStart()), Integer.valueOf(param.getPageSize()), pkRoles.toArray(new String[0]), param.getPkOrgs());
        userInfoQuery.tranUserInfoField(result.getObjects(), new String[]{ProjectVO.MANAGER}, new String[]{ProjectVO.MANAGER_NAME});
        return result;
    }

    @RequestMapping("/queryByCondition")
    public PageObject<ProjectWithProblemVO> queryByCondition(@RequestBody ProjectSearchConditionVO searchConditionVO)
            throws BusinessException, IOException {
        if (searchConditionVO == null || StringUtils.isEmpty(searchConditionVO.getCondition())) {
            return new PageObject<>(new ProjectWithProblemVO[0], 0, 0);
        }

        String condition = searchConditionVO.getCondition();
        int pageStart = searchConditionVO.getPageStart();
        int pageSize = searchConditionVO.getPageSize() == 0 ? CommonProgramConsts.DEFAULT_MAX_QUERY_SIZE : searchConditionVO.getPageSize();

        List<String> pkRoles = getPkRoles();
        searchConditionVO.setPkRoles(pkRoles.toArray(new String[]{}));

        ProjectWithProblemVO[] projectWithProblemVOS = query.queryOfCondition(searchConditionVO);

        userInfoQuery.tranUserInfoField(projectWithProblemVOS, new String[]{ProjectWithProblemVO.MANAGER}, new String[]{ProjectWithProblemVO.MANAGER_NAME});

        List<ProjectWithProblemVO> newProjectVOS = new ArrayList<>();

        for (ProjectWithProblemVO projectWithProblemVO : projectWithProblemVOS) {
            String scode = isEmpty(projectWithProblemVO.getScode());
            String sname = isEmpty(projectWithProblemVO.getSname());
            String managerName = isEmpty(projectWithProblemVO.getManagerName());
            String orgName = isEmpty(projectWithProblemVO.getOrgName());

            if (!scode.contains(condition) && !sname.contains(condition) && !managerName.contains(condition) &&
                    !orgName.contains(condition)) {
                continue;
            }
            newProjectVOS.add(projectWithProblemVO);
        }

        if (newProjectVOS.size() <= 0) {
            return new PageObject<>(new ProjectWithProblemVO[0], 0, searchConditionVO.getPageStart());
        }

        ProjectWithProblemVO[] newProjectWithProblemVOS = newProjectVOS.toArray(new ProjectWithProblemVO[]{});

        //  这里做分页，减小问题和计划的查询
        newProjectWithProblemVOS = ArrayUtils.subarray(newProjectWithProblemVOS, pageStart, pageStart + pageSize);

        return new PageObject<>(newProjectWithProblemVOS, newProjectWithProblemVOS.length, searchConditionVO.getPageStart());
    }

    private String isEmpty(String string) {
        string = StringUtils.isEmpty(string) ? "" : string;
        return string;
    }

    private List<String> getPkRoles() throws IOException {
        return userOperator.getPkRoles(RuntimeEnvironment.getTenantId(), RuntimeEnvironment.getLoginUserId());
    }

    /**
     * 通过用户地址匹配项目
     *
     * @param longitude
     * @param latitude
     * @return
     * @throws BusinessException
     */
    @RequestMapping("/matchByAddress")
    public ProjectRefVO matchByAddress(@RequestParam("longitude") double longitude,
                                       @RequestParam("latitude") double latitude,
                                       @RequestParam(name = "isMakeBill", required = false, defaultValue = "false") Boolean isMakeBill,
                                       @RequestParam(name = "projectState", required = false) Byte[] projectState,
                                       @RequestParam(name = "pkTenant", required = false) String pkTenant) throws BusinessException, IOException {

        PageObject<?> refVOPage = this.list(pkTenant, isMakeBill, projectState,
                DEFAULT_PAGE_PAGE_START, "1000", longitude, latitude);

        ProjectRefVO result;
        if (refVOPage != null && ArrayUtils.isNotEmpty(refVOPage.getObjects())) {
            result = (ProjectRefVO) refVOPage.getObjects()[0];
            if (result.getDistance() != null && PROJECT_ADDRESS_RANGE > result.getDistance()) {
                return result;
            }
        }

        return new ProjectRefVO();
    }

}

@Data
class ListWithProblemParam implements Serializable {
    private static final long serialVersionUID = 5164552426304500471L;
    private String pkTenant;
    private String projectState;
    private String[] pkOrgs;
    private String pageStart = "0";
    private String pageSize = "1000";

}
